package com.wx.commons.annotation;

import com.wx.commons.utils.IpAddressUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
@Slf4j
public class IdempotentAspect {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Pointcut("@annotation(com.wx.commons.annotation.Idempotent)")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void intercept(JoinPoint joinPoint) {

        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String ip = IpAddressUtil.getIpAddress(request);
        String className = joinPoint.getTarget().getClass().getName();
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        String methodName = method.getName();
        Idempotent idempotent = method.getAnnotation(Idempotent.class);
        long timeout = idempotent.timeout();

        String key = ip + "," + className + "," + methodName + "," + timeout;
        String value = redisTemplate.opsForValue().get(key);
        if (value != null) {
            throw new RuntimeException("不能在" + timeout + "s内重复提交");
        }
        redisTemplate.opsForValue().set(key, key, timeout, TimeUnit.SECONDS);
    }


}
